package cn.cdzdjd.aspect;

import java.lang.reflect.Method;
import java.time.LocalDateTime;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.annotation.Pointcut;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.HttpHeaders;
import org.springframework.stereotype.Component;

import cn.cdzdjd.annotation.Log;
import cn.cdzdjd.entity.Notice;
import cn.cdzdjd.entity.VideoLog;
import cn.cdzdjd.service.EMailService;
import cn.cdzdjd.service.NoticeService;
import cn.cdzdjd.service.VideoLogService;
import cn.cdzdjd.util.HttpContextUtils;
import cn.cdzdjd.util.IpUtils;
import cn.cdzdjd.util.JsonUtils;
import cn.cdzdjd.util.UserHolder;
import io.netty.util.internal.ThrowableUtil;

@Aspect
@Component
//@Slf4j
public class VLogAspect {
	@Value("${spring.mail.username}")
	private String email;
	@Resource
	private VideoLogService videoLogService;
	@Resource
	private EMailService emailService;
	@Resource
	private NoticeService noticeService;

	@Pointcut("@annotation(cn.cdzdjd.annotation.Log)")
	public void logPointCut() {

	}

	@Around("logPointCut()")
	public Object around(ProceedingJoinPoint point) throws Throwable {
		long beginTime = System.currentTimeMillis();
		try {
			// 执行方法
			Object result = point.proceed();

			// 执行时长(毫秒)
			long time = System.currentTimeMillis() - beginTime;
			// 保存日志
			saveLog(point, time, null);
			return result;
		} catch (Exception e) {
			if (e instanceof NullPointerException) {
				Notice notice = new Notice();
				notice.setType("user");
				notice.setContent("系统发现个别链接解析异常，已通知技术人员进行修复");
				notice.setCreateBy(UserHolder.getHolder());
				notice.setCreateDate(LocalDateTime.now());
				notice.setShowEndtime(LocalDateTime.now().plusHours(2));
				noticeService.insertNotice(notice);
				emailService.sendMail(email, email, email, "服务器出异常啦,请及时查看异常信息",
						"异常内容为:" + ThrowableUtil.stackTraceToString(e));
			}
			// 执行时长(毫秒)
			long time = System.currentTimeMillis() - beginTime;
			// 保存日志
			saveLog(point, time, ThrowableUtil.stackTraceToString(e));
			throw e;
		}
	}

	private void saveLog(JoinPoint joinPoint, long time, String errorInfo) throws Exception {
		MethodSignature signature = (MethodSignature) joinPoint.getSignature();
		Method method = joinPoint.getTarget().getClass().getDeclaredMethod(signature.getName(),
				signature.getParameterTypes());
		Log annotation = method.getAnnotation(Log.class);

		VideoLog log = new VideoLog();

		log.setErrorInfo(errorInfo);
		if (annotation != null) {
			// 注解上的描述
			log.setAnnoValue(annotation.value());
		}

		// 登录用户信息
		Long userId = UserHolder.getHolder();
		if (userId != null) {
			log.setCreator(userId);
		}
		log.setTime((int) time);
		// 请求相关信息
		HttpServletRequest request = HttpContextUtils.getHttpServletRequest();
		log.setIp(IpUtils.getIpAddr(request));
		log.setUserAgent(request.getHeader(HttpHeaders.USER_AGENT));
		log.setRequestUri(request.getRequestURI());
		log.setRequestMethod(request.getMethod());

		// 请求参数
		Object[] args = joinPoint.getArgs();
		try {
			String params = JsonUtils.toJsonString(args[0]);
			log.setRequestParams(params);
		} catch (Exception e) {

		}
		try {
			// 方法路径
			String methodName = joinPoint.getTarget().getClass().getName() + "." + signature.getName() + "()";
			log.setMethod(methodName);
		} catch (Throwable e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		// 保存到DB
		videoLogService.insert(log);
	}
}
